﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Novel.Server.Models;
using Novel.Server.Response;

namespace Novel.Server.Controllers
{
    [Route("api/stats")]
    [ApiController]
    public class StatsController : ControllerBase
    {
        private readonly NovelContext dbContext;
        private readonly IConfiguration conf;

        public StatsController(NovelContext context, IConfiguration configuration)
        {
            dbContext = context;
            conf = configuration;
        }

        /// <summary>
        /// 统计小说数量
        /// </summary>
        [HttpGet("novel")]
        [Authorize(Roles = "admin")]
        public async Task<IActionResult> newNovelByDayLastMonth()
        {
            var today = DateTime.Today;
            var lastMonth = today.AddMonths(-1);
            var novelCounts = await dbContext.Novels
                .Where(n => n.CreatedAt >= lastMonth && !n.IsDeleted)
                .GroupBy(c => c.CreatedAt.Date)
                .Select(g => new CountResult
                {
                    Date = g.Key,
                    Count = g.Count(),
                })
                .OrderBy(g => g.Date)
                .ToListAsync();
            return await formatList(novelCounts, lastMonth, today);
        }

        /// <summary>
        /// 统计评论数量
        /// </summary>
        [HttpGet("comment")]
        [Authorize(Roles = "admin")]
        public async Task<IActionResult> newCommentByDayLastMonth()
        {
            var today = DateTime.Today;
            var lastMonth = today.AddMonths(-1);
            var commentCounts = await dbContext.Comments
                .Where(n => n.CreatedAt >= lastMonth && !n.IsDeleted)
                .GroupBy(c => c.CreatedAt.Date)
                .Select(g => new CountResult
                {
                    Date = g.Key,
                    Count = g.Count(),
                })
                .OrderBy(g => g.Date)
                .ToListAsync();
            return await formatList(commentCounts, lastMonth, today);
        }

        /// <summary>
        /// 统计用户数量
        /// </summary>
        [HttpGet("user")]
        [Authorize(Roles = "admin")]
        public async Task<IActionResult> newUserByDayLastMonth()
        {
            var today = DateTime.Today;
            var lastMonth = today.AddMonths(-1);
            var novelCounts = await dbContext.Users
                .Where(n => n.CreatedAt >= lastMonth && !n.IsDeleted)
                .GroupBy(c => c.CreatedAt.Date)
                .Select(g => new CountResult
                {
                    Date = g.Key,
                    Count = g.Count(),
                })
                .OrderBy(g => g.Date)
                .ToListAsync();
            return await formatList(novelCounts, lastMonth, today);
        }

        private Task<IActionResult> formatList(List<CountResult> commentCounts, DateTime firstDay, DateTime lastDay)
        {
            // wrap following codes into a function so can be reused
            var allDates = Enumerable.Range(0, (lastDay - firstDay).Days + 1)
                .Select(offset => firstDay.AddDays(offset))
                .ToList();

            var result = allDates
                .GroupJoin(commentCounts,
                    date => date,
                    comment => comment.Date,
                    (date, commentGroup) => new
                    {
                        date = date,
                        count = commentGroup.FirstOrDefault()?.Count ?? 0,
                    })
                .OrderBy(x => x.date)
                .ToList();

            return Task.FromResult<IActionResult>(Ok(ApiResponse.SuccessResponse(result)));
        }

        private class CountResult
        {
            public DateTime Date { get; set; }
            public int Count { get; set; }
        }
    }
}
